﻿// ***********************************************************************
// Project          : Micua.Infrastructure
// Assembly         : Micua.Utility
// Author           : Administrator
// Created          : 2014-01-11 3:14 PM
// 
// Last Modified By : Administrator
// Last Modified On : 2014-01-11 3:14 PM
// ***********************************************************************
// <copyright file="Config.cs" company="Wedn.Net">
//     Copyright (c) Wedn.Net. All rights reserved.
// </copyright>
// <summary></summary>
// ***********************************************************************

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using Micua.Utility.Properties;

namespace Micua.Utility
{
    /// <summary>
    /// 配置阶段操作助手
    /// </summary>
    public static class ConfigHelper
    {
        ///// <summary>
        ///// 配置节点名称
        ///// </summary>
        //public static readonly string SectionName { get; private set; }
        private static string _configPath
        {
            get
            {
                return ApplicationHelper.MapPath("~/config/");
            }
        }
        private static string _configFile
        {
            get
            {
                var configName = ConfigurationManager.AppSettings["config_name"] ?? "micua";
#if DEBUG
                return configName + ".debug.config";
#else
                return configName + ".conf.config";
#endif
            }
        }
        /// <summary>
        /// 配置数据
        /// </summary>
        public static IDictionary<string, string> Configs { get; private set; }
        /// <summary>
        /// 配置操作助手类
        /// </summary>
        static ConfigHelper()
        {
            RefreshConfigs();
            //监视配置文件修改
            FileSystemWatcher watcher = new FileSystemWatcher(_configPath, _configFile);
            watcher.EnableRaisingEvents = true;
            watcher.NotifyFilter = NotifyFilters.LastWrite;
            watcher.Changed += watcher_Changed;
            //watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastAccess
            //                     | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;
            //watcher.IncludeSubdirectories = true;
        }

        /// <summary>
        /// 配置文件发生变化事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void watcher_Changed(object sender, FileSystemEventArgs e)
        {
            //ConfigurationManager.RefreshSection(SectionName);
            //_configSection = null;
            Configs = null;
            var flag = RefreshConfigs();
            //var thread = new Thread((obj) =>
            //{
            //    Configs = null;
            //    var flag = RefreshConfigs();
            //    while (!flag)
            //    {
            //        Thread.Sleep(5000);
            //        flag = RefreshConfigs();
            //    }
            //    var t = obj as Thread;
            //    if (t != null)
            //        t.Abort();
            //});
            //thread.Start(thread);
        }
        /// <summary>
        /// 刷新配置方法
        /// </summary>
        private static bool RefreshConfigs()
        {
            lock ("ConfigHelper")
            {
                if (Configs == null)
                {
                    var filePath = _configPath + _configFile;
                    if (!File.Exists(filePath))
                    {
                        throw new ConfigurationErrorsException(string.Format(Resources.configuration_file_0_not_found, _configFile));
                    }
                    else
                    {
                        //防止文件被占用
                        //string tempFile = Path.Combine(_configPath, Guid.NewGuid().ToString("N") + ".txt");
                        //File.Copy(filePath, tempFile);
                        //var json = File.ReadAllText(filePath);
                        //File.Delete(tempFile);

                        //try
                        //{
                        //    var obj = JsonHelper.Deserialize<IDictionary<string, string>>(File.ReadAllText(filePath));
                        //    if (obj == null)
                        //    {
                        //        throw new ConfigurationErrorsException(string.Format(Resources.configuration_file_0_does_not_pass_validation, _configFile));
                        //    }
                        //    Configs = obj;
                        //}
                        //catch (Exception)
                        //{
                        //    return false;
                        //}
                        var doc = new XmlDocument();
                        var settings = new XmlReaderSettings();
                        settings.IgnoreComments = true;//忽略Xml中的注释  
                        settings.IgnoreWhitespace = true;//忽略没必要的空白  
                        try
                        {
                            using (var reader = XmlReader.Create(filePath, settings))
                            {
                                doc.Load(reader);
                            }
                            if (doc == null) { throw new ConfigurationErrorsException(string.Format(Resources.configuration_file_0_does_not_pass_validation, _configFile)); }
                            XmlNode root = doc.DocumentElement;
                            if (root == null) { throw new ConfigurationErrorsException(string.Format(Resources.configuration_file_0_does_not_pass_validation, _configFile)); }
                            if (root.HasChildNodes)
                            {
                                Configs = new Dictionary<string, string>();
                                foreach (XmlNode item in root.ChildNodes)
                                {
                                    Configs.Add(item.Attributes["key"].Value.ToLower(), item.Attributes["value"].Value);
                                }
                            }
                        }
                        catch (Exception)
                        {
                             return false;
                        }
                    }
                }
                return true;
                //if (_configSection == null)
                //{
                //    var obj = ConfigurationManager.GetSection(SectionName);
                //    if (obj == null || !(obj is NameValueCollection))
                //    {
                //        throw new ConfigurationErrorsException(string.Format(Resources.configuration_file_0_does_not_pass_validation, ""));
                //    }
                //    _configSection = ConfigurationManager.GetSection(SectionName) as NameValueCollection;
                //}
            }
        }

        #region 获取String类型配置信息 +static string GetString(string key, string def = "")
        /// <summary>
        /// 获取字符串类型配置信息
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static string GetString(string key, string def = "")
        {
            //if (_configSection != null) return _configSection[key] ?? def;
            //RefreshConfig();
            //return _configSection != null ? (_configSection[key] ?? def) : def;
            //if (Configs == null)
            //    RefreshConfigs();
            key = key.ToLower();
            return Configs != null && Configs.ContainsKey(key) ? Configs[key] : def;
        }
        #endregion

        #region 获取泛型类型的配置信息（JSON格式） +static T Get<T>(string key, T def = null) where T : class
        /// <summary>
        /// 获取泛型类型的配置信息（JSON格式）
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <typeparam name="T">配置类型</typeparam>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>制定类型的配置信息</returns>
        public static T Get<T>(string key, T def = null) where T : class
        {
            var json = GetString(key);
            try
            {
                return JsonHelper.Deserialize<T>(json);
            }
            catch (System.Exception)
            {
                return def;
            }
        }
        #endregion

        #region 获取Boolean类型配置信息值 +static bool GetBoolean(string key, bool def = default(Boolean))
        /// <summary>
        /// 获取Boolean类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static bool GetBoolean(string key, bool def = default(Boolean))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            Boolean.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取Char类型配置信息值 +static char GetChar(string key, char def = default(Char))
        /// <summary>
        /// 获取Char类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static char GetChar(string key, char def = default(Char))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            Char.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取Decimal类型配置信息值 +static decimal GetDecimal(string key, decimal def = default(Decimal))
        /// <summary>
        /// 获取Decimal类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static decimal GetDecimal(string key, decimal def = default(Decimal))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            Decimal.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取Double类型配置信息值 +static double GetDouble(string key, double def = default(Double))
        /// <summary>
        /// 获取Double类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static double GetDouble(string key, double def = default(Double))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            Double.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取Single类型配置信息值 +static float GetSingle(string key, float def = default(Single))
        /// <summary>
        /// 获取Single类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static float GetSingle(string key, float def = default(Single))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            Single.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取Byte类型配置信息值 +static byte GetByte(string key, byte def = default(Byte))
        /// <summary>
        /// 获取Byte类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static byte GetByte(string key, byte def = default(Byte))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            Byte.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取SByte类型配置信息值 +static sbyte GetSByte(string key, sbyte def = default(SByte))
        /// <summary>
        /// 获取SByte类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static sbyte GetSByte(string key, sbyte def = default(SByte))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            SByte.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取Int16类型配置信息值 +static short GetInt16(string key, short def = default(Int16))
        /// <summary>
        /// 获取Int16类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static short GetInt16(string key, short def = default(Int16))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            Int16.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取UInt16类型配置信息值 +static ushort GetUInt16(string key, ushort def = default(UInt16))
        /// <summary>
        /// 获取UInt16类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static ushort GetUInt16(string key, ushort def = default(UInt16))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            UInt16.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取Int32类型配置信息值 +static int GetInt32(string key, int def = default(Int32))
        /// <summary>
        /// 获取Int32类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static int GetInt32(string key, int def = default(Int32))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            Int32.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取UInt32类型配置信息值 +static uint GetUInt32(string key, uint def = default(UInt32))
        /// <summary>
        /// 获取UInt32类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static uint GetUInt32(string key, uint def = default(UInt32))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            UInt32.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取Int64类型配置信息值 +static long GetInt64(string key, long def = default(Int64))
        /// <summary>
        /// 获取Int64类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static long GetInt64(string key, long def = default(Int64))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            Int64.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取UInt64类型配置信息值 +static ulong GetUInt64(string key, ulong def = default(UInt64))
        /// <summary>
        /// 获取UInt64类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static ulong GetUInt64(string key, ulong def = default(UInt64))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            UInt64.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取DateTime类型配置信息值 +static DateTime GetDateTime(string key, DateTime def = default(DateTime))
        /// <summary>
        /// 获取DateTime类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static DateTime GetDateTime(string key, DateTime def = default(DateTime))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            DateTime.TryParse(res, out def);
            return def;
        }
        #endregion

        #region 获取Guid类型配置信息值 +static Guid GetGuid(string key, Guid def = default(Guid))
        /// <summary>
        /// 获取Guid类型配置信息值
        /// </summary>
        /// <remarks>
        ///  2013-11-23 14:27 Created By iceStone
        /// </remarks>
        /// <param name="key">设置键</param>
        /// <param name="def">缺省值</param>
        /// <returns>设置值</returns>
        public static Guid GetGuid(string key, Guid def = default(Guid))
        {
            var res = GetString(key);
            if (res.Length == 0) return def;
            Guid.TryParse(res, out def);
            return def;
        }
        #endregion
    }
}